#include "include.h"
#include "update_image.h"
#include "sys_irq.h"
#include "driver_flash.h"
/*****************************************************************************************************/
/**************************************CFG_UPDATE_IMAGE***********************************************/
/*****************************************************************************************************/
u_int32 udi_set_section_status_A_B(SECTION_BOUNDARY_PTR left, SECTION_BOUNDARY_PTR right)
{
    u_int32 status = SSTATUS_UNKOWN;
    if((FLASH_ERASED_CODE == left->signature)
            && (FLASH_ERASED_CODE == left->rsv[0])
            && (FLASH_ERASED_CODE == right->signature)
            && (FLASH_ERASED_CODE == right->rsv[0]))
    {
        status = SSTATUS_SECT_ERASED;
        goto exit_point;
    }
    if((UDI_SIGNATURE_CODE != left->signature) || (left->version != right->version))
    {
        status = SSTATUS_UPDATE_ABNORMAL;
        goto exit_point;
    }
    else
    {
        status = SSTATUS_UPDATE_NORMAL;
    }
    return status;
exit_point:
    return status;
}
void udi_get_psec_40_A_boundry(void)
{
    uint32 p_right_boundary_addr;
    fflash_rd_data((u_int8 *)&psec_A.left_boundary, (u_int32)PSEC_40_CRC_A_LEFT_BOUNDARY_ADDR, sizeof(psec_A.left_boundary));
    if(UDI_SIGNATURE_CODE == psec_A.left_boundary.signature)
    {
        p_right_boundary_addr = psec_A.left_boundary.sec_size + PSEC_40_A_LEFT_BOUNDARY_ADDR;
        fflash_rd_data((u_int8 *)&psec_A.right_boundary, crc_address(p_right_boundary_addr), sizeof(psec_A.right_boundary));
    }
    else
    {
        udi_memcpy(&psec_A.right_boundary, &psec_A.left_boundary, sizeof(psec_A.left_boundary));
    }
}
void udi_get_psec_40_B_boundry(void)
{
    uint32 p_right_boundary_addr;
    fflash_rd_data((u_int8 *)&psec_B.left_boundary, (u_int32)PSEC_40_CRC_B_LEFT_BOUNDARY_ADDR, sizeof(psec_B.left_boundary));
    DEBUG_MSG(0XD1);
    DEBUG_MSG(0XD2);
    if(UDI_SIGNATURE_CODE == psec_B.left_boundary.signature)
    {
        DEBUG_MSG(0XD3);
        p_right_boundary_addr = psec_B.left_boundary.sec_size + PSEC_40_B_LEFT_BOUNDARY_ADDR;
        fflash_rd_data((u_int8 *)&psec_B.right_boundary, crc_address(p_right_boundary_addr), sizeof(psec_B.right_boundary));
    }
    else
    {
        udi_memcpy(&psec_B.right_boundary, &psec_B.left_boundary, sizeof(psec_B.left_boundary));
    }
}
u_int32 udi_updating_begin(u_int32 version, u_int32 total_len)
{
#ifdef OAD_IMAGE_A
    flash_set_line_mode(1);
    flash_write_sr(2,0x022c);
    flash_set_line_mode(4);
    
    bsec_B.left_boundary.sec_size = total_len;
    bsec_B.update_offset = 0;
    return bsec_B.left_boundary.sec_size;
#endif
#ifdef OAD_IMAGE_B
    flash_set_line_mode(1);
    flash_write_sr(2,0x0203);
    flash_set_line_mode(4);
    bsec_A.left_boundary.sec_size = total_len;
    bsec_A.update_offset = 0;
    return bsec_A.left_boundary.sec_size;
#endif
}
u_int32 udi_updating_section(u_int8 *buf, u_int32 len)
{
    u_int32 wr_addr;
    UDI_SECTION_PTR sec_ptr;
#ifdef OAD_IMAGE_A
    sec_ptr = &bsec_B;
#endif
#ifdef OAD_IMAGE_B
    sec_ptr = &bsec_A;
#endif

#ifdef OAD_IMAGE_A
    wr_addr = sec_ptr->update_offset + (PSEC_40_CRC_IMAGE_B_ADDR );
#endif
#ifdef  OAD_IMAGE_B
    wr_addr = sec_ptr->update_offset + (PSEC_40_CRC_IMAGE_A_ADDR );
#endif

    fflash_wr_data(buf, wr_addr, len);
    
    sec_ptr->update_offset += len;
    return 0;
}
u_int32 flash_srr;

u_int32 udi_updating_end(void)
{
	uint8 readData[32] = {0},i;
#ifdef  OAD_IMAGE_A
    uint32 invalidData[8] = {0};
    
	
    DEBUG_MSG(0XD7);
    udi_get_psec_40_B_boundry();
    psec_B.sect_status = udi_set_section_status_A_B(&psec_B.left_boundary, &psec_B.right_boundary);
    if(SSTATUS_UPDATE_NORMAL == psec_B.sect_status)
    {
    
        DEBUG_MSG(0XD8);
        
        flash_set_line_mode(1);
        flash_write_sr( 2, 0X0203 );
        udi_memset32(invalidData,0,8);
        fflash_wr_data((uint8 *)invalidData,PSEC_40_CRC_A_LEFT_BOUNDARY_ADDR,32);
        fflash_rd_data(readData,PSEC_40_CRC_A_LEFT_BOUNDARY_ADDR,32);
        for(i=0;i<32;i++)
            DEBUG_MSG(readData[i]);
        flash_set_line_mode(1);
        flash_write_sr( 2, 0X0210 );
        DEBUG_MSG(0XD9);            
    }
#endif
#ifdef  OAD_IMAGE_B
        uint32 invalidData[8] = {0};
        udi_get_psec_40_A_boundry();
        psec_A.sect_status = udi_set_section_status_A_B(&psec_A.left_boundary, &psec_A.right_boundary);
        if(SSTATUS_UPDATE_NORMAL == psec_A.sect_status)
        {
            DEBUG_MSG(0XD8);
            flash_set_line_mode(1);
            flash_write_sr( 2, 0X022c );
            udi_memset32(invalidData,0,8);
            fflash_wr_data((uint8 *)invalidData,PSEC_40_CRC_B_LEFT_BOUNDARY_ADDR,32);
            fflash_rd_data(readData,PSEC_40_CRC_A_LEFT_BOUNDARY_ADDR,32);
            for(i=0;i<32;i++)
                DEBUG_MSG(readData[i]);
            flash_set_line_mode(1);
            flash_write_sr( 2, 0X0210 );
            DEBUG_MSG(0XD9);   
        }
#endif

    udi_reset();

    return 0;
}
void udi_init_A_B(void)
{
    udi_hex_int_print(0X01);
    udi_wdt_disable();
    udi_icu_init();
    udi_uart_init();
    fflash_initialization();
    udi_delay_ms(50);
}
void udi_uninit(void)
{
}
void udi_imageB_check(void)
{
    uint32 p_right_boundary_addr;
    fflash_rd_data((u_int8 *)&psec_B.left_boundary, (u_int32)PSEC_40_CRC_B_LEFT_BOUNDARY_ADDR, sizeof(psec_B.left_boundary));
    if(UDI_SIGNATURE_CODE == psec_B.left_boundary.signature)
    {
        p_right_boundary_addr = psec_B.left_boundary.sec_size + PSEC_40_B_LEFT_BOUNDARY_ADDR;
        fflash_rd_data((u_int8 *)&psec_B.right_boundary, crc_address(p_right_boundary_addr), sizeof(psec_B.right_boundary));
    }
    else
    {
        udi_memcpy(&psec_B.right_boundary, &psec_B.left_boundary, sizeof(psec_B.left_boundary));
    }
}
extern int FAST_ENTRY0 main(void);
u_int32 udi_handler_A_B(void)
{
    udi_hex_int_print(0x02);
    main();
    return 0;
}
int udi_main_40_A_B(void)
{
#ifdef OAD_IMAGE_A
    udi_memset32((u_int8 *)0x00400000, 1, 1);
#else
    udi_memset32((u_int8 *)0x00400000, 0, 1);
#endif
    udi_init_A_B();
    udi_handler_A_B();
    return 0;
}
